home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-01-06 | 7.8 KB | 372 lines | [TEXT/MMCC] |
- //
- // CTelnetInterp.cp
- //
- // TurboTCP library
- // Generic Telnet protocol interpreter
- //
- // Copyright © 1993-95, FrostByte Design / Eric Scouten
- //
-
- #include "CTelnetInterp.h"
-
- #if TurboTCP_TCL
- TCL_DEFINE_CLASS_M1(CTelnetInterp, CTCPEndpoint);
- #endif
-
-
- //***********************************************************
-
- CTelnetInterp::CTelnetInterp
- (unsigned short theDefaultPort, // default IP port number (the only required parameter)
- unsigned long recBufferSize, // size of receive buffer to create
- unsigned short autoReceiveSize, // number of entries in RDS for auto receive
- unsigned short autoReceiveNum, // number of auto-receive calls to issue at once
- Boolean doUseCName) // true to get canonical name of remote host
- // whenever possible
-
- : CTCPEndpoint(theDefaultPort, recBufferSize, autoReceiveSize, autoReceiveNum, doUseCName)
-
- {
- itsState = normalChar;
- showFileName = false;
- }
-
-
- //***********************************************************
- //
- // Telnet command handling methods
- //
- // If you wish to respond to specific Telnet commands, override these methods.
- // You may ignore any or all of these methods.
- //
-
- //***********************************************************
-
- void CTelnetInterp::ReceivedWill // protected method
- (uchar theOption) // the option number
-
- // Respond to a Telnet [IAC WILL option] sequence. Default method responds [WONT option].
- // Override to implement any Telnet options, call this method to reject any unimplemented
- // options.
-
-
- {
- char respondStr[4];
-
-
- // reject all options
-
- respondStr[0] = charIAC;
- respondStr[1] = escWONT;
- respondStr[2] = theOption;
- respondStr[3] = '\0';
- if (showDebug) {
- PrintDebugStr("{IAC WONT");
- PrintDebugCharNum(theOption, ' ', '}');
- }
- *this << respondStr;
- }
-
-
- //***********************************************************
-
- void CTelnetInterp::ReceivedDo // protected method
- (uchar theOption) // the option number
-
- // Respond to a Telnet [IAC DO option] sequence. Default method responds [WONT option].
- // Override to implement any Telnet options, call this method to reject any unimplemented
- // options.
-
- {
- char respondStr[4];
-
-
- // reject all options
-
- respondStr[0] = charIAC;
- respondStr[1] = escWONT;
- respondStr[2] = theOption;
- respondStr[3] = '\0';
- if (showDebug) {
- PrintDebugStr("{IAC WONT");
- PrintDebugCharNum(theOption, ' ', '}');
- }
- *this << respondStr;
- }
-
-
- //***********************************************************
-
- void CTelnetInterp::ReceivedSB // protected method
- (uchar theChar) // the latest character
-
- // Receive subnegotiation parameters. Buffers characters until SE is received.
-
- {
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', '\0');
- sbBfr[sbBfrIndex++] = theChar;
- }
-
-
- // -- respond to incoming data (do not override) --
-
- //***********************************************************
-
- void CTelnetInterp::HandleDataArrived // private method — DO NOT OVERRIDE!
- (void* theData, // pointer to block of data
- unsigned short theDataSize, // size of data block
- Boolean isUrgent) // true if urgent data
-
- // Process incoming data. This is the guts of the Telnet interpreter.
- // Your subclass must not override this method. You must instead override
- // HandleNVTChar and HandleNVTLine to process data intended for the
- // “terminal” that you are implementing.
-
- {
- char* xData = (char*) theData; // hack to avoid lots of typecasts
- uchar theChar;
- char theLine[83];
- short lineIndex;
-
-
- // parse each character separately
-
- while (theDataSize--) {
- theChar = (uchar) (*(xData++));
-
-
- // respond to current Telnet state
-
- switch (itsState) {
-
-
- // normal operation: write character
-
- case normalChar:
-
-
- // optimization: try to grab several chars at once
-
- lineIndex = 0;
- while ((theDataSize > 1) && (theChar >= ' ') && (theChar != charIAC)) {
- theDataSize++;
- xData--;
- lineIndex = 0;
- while ((theDataSize > 0) && (((uchar) *xData) >= ' ') &&
- (*xData != charIAC) && (lineIndex < 80))
- theDataSize--, theLine[lineIndex++] = (uchar) *(xData++);
- if ((theDataSize > 0) && (*xData == charCR))
- theDataSize--, xData++, theLine[lineIndex++] = charCR;
- if ((theDataSize > 0) && (*xData == charLF))
- theDataSize--, xData++, theLine[lineIndex++] = charLF;
- theLine[lineIndex] = '\0';
- if (lineIndex)
- HandleNVTLine((char*) &theLine[0]);
- if (theDataSize < 1)
- break;
- theChar = (uchar) (*(xData++));
- theDataSize--;
- }
-
- if ((lineIndex) && !(theDataSize))
- break;
-
-
- // end of loop: test for IAC
-
- if (theChar == charIAC) {
- itsState = gotIAC;
- if (showDebug)
- PrintDebugStr("[IAC");
- }
- else
- HandleNVTChar(theChar);
- break;
-
-
- // received IAC (interpret as command)
-
- case gotIAC:
- case gotIACinSB:
- ReceivedIAC(theChar);
- break;
-
-
- // handle other cases
-
- case gotSB:
- if (theChar == charIAC) {
- itsState = gotIACinSB;
- if (showDebug)
- PrintDebugStr(" IAC");
- }
- else
- ReceivedSB(theChar);
- break;
-
- case gotWILL:
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', ']');
- ReceivedWill(theChar);
- itsState = normalChar;
- break;
-
- case gotWONT:
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', ']');
- ReceivedWont(theChar);
- itsState = normalChar;
- break;
-
- case gotDO:
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', ']');
- ReceivedDo(theChar);
- itsState = normalChar;
- break;
-
- case gotDONT:
- if (showDebug)
- PrintDebugCharNum(theChar, ' ', ']');
- ReceivedDont(theChar);
- itsState = normalChar;
- break;
- }
- }
-
- }
-
-
- //***********************************************************
-
- void CTelnetInterp::ReceivedIAC // private method
- (uchar theCommand) // the command number
-
- // Respond to a Telnet [IAC command] sequence.
- // As with HandleDataArrived, this method should not be overriden.
-
- {
-
- // which command is it?
-
- switch (theCommand) {
-
- case escSE:
- if (showDebug)
- PrintDebugStr(" SE]");
- sbBfr[sbBfrIndex] = '\0';
- if (itsState == gotIACinSB)
- ReceivedSE();
- itsState = normalChar;
- break;
-
- case escNOP:
- if (showDebug)
- PrintDebugStr(" NOP]");
- itsState = normalChar;
- break;
-
- case escDM:
- if (showDebug)
- PrintDebugStr(" DM]");
- ReceivedSynch();
- itsState = normalChar;
- break;
-
- case escBRK:
- if (showDebug)
- PrintDebugStr(" BRK]");
- ReceivedBRK();
- itsState = normalChar;
- break;
-
- case escIP:
- if (showDebug)
- PrintDebugStr(" IP]");
- ReceivedIP();
- itsState = normalChar;
- break;
-
- case escAO:
- if (showDebug)
- PrintDebugStr(" AO]");
- ReceivedAO();
- itsState = normalChar;
- break;
-
- case escAYT:
- if (showDebug)
- PrintDebugStr(" AYT]");
- ReceivedAYT();
- itsState = normalChar;
- break;
-
- case escEC:
- if (showDebug)
- PrintDebugStr(" EC]");
- ReceivedEC();
- itsState = normalChar;
- break;
-
- case escEL:
- if (showDebug)
- PrintDebugStr(" EL]");
- ReceivedEL();
- itsState = normalChar;
- break;
-
- case escGA:
- if (showDebug)
- PrintDebugStr(" GA]");
- ReceivedGA();
- itsState = normalChar;
- break;
-
- case escSB:
- if (showDebug)
- PrintDebugStr(" SB");
- itsState = gotSB;
- sbBfrIndex = 0;
- break;
-
- case escWILL:
- if (showDebug)
- PrintDebugStr(" WILL");
- itsState = gotWILL;
- break;
-
- case escWONT:
- if (showDebug)
- PrintDebugStr(" WONT");
- itsState = gotWONT;
- break;
-
- case escDO:
- if (showDebug)
- PrintDebugStr(" DO");
- itsState = gotDO;
- break;
-
- case escDONT:
- if (showDebug)
- PrintDebugStr(" DONT");
- itsState = gotDONT;
- break;
-
- case escIAC:
- default:
- if (itsState == gotIACinSB) {
- ReceivedSB(theCommand);
- itsState = gotIAC;
- }
- else {
- if (showDebug)
- PrintDebugCharNum(theCommand, '?', ']');
- HandleNVTChar(theCommand);
- itsState = normalChar;
- }
- }
-
- }
-